package com.liuya.safe.system.role.service.impl;

import java.sql.SQLException;
import java.util.*;

import com.liuya.base.AbstractBaseService;
import com.liuya.common.exception.EntityExistException;
import com.liuya.common.I18N;
import com.liuya.db.DBLevelException;
import com.liuya.db.util.DBUtil;
import com.liuya.safe.entitle.service.PrivilegeManagerService;
import com.liuya.safe.model.RolePrivilege;
import com.liuya.safe.model.SafePrivilege;
import com.liuya.safe.model.SafeRole;
import com.liuya.safe.policy.service.UserCategoryManagerService;
import com.liuya.safe.system.role.dao.RolePrivilegeMapper;
import com.liuya.safe.system.role.dao.SafeRoleMapper;

import com.liuya.safe.system.role.service.RoleManagerService;
import com.liuya.safe.user.service.UserRoleManagerService;
import com.liuya.safe.util.Constants;
import com.liuya.safe.util.Factory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author liuya
 * @date 20160830
 */
@Service("roleManagerService")
@Transactional
public class RoleManagerServiceImpl extends AbstractBaseService<SafeRole> implements RoleManagerService{

	private static final String ADMINISTRATOR_ID = "-1";
	private String appName;

//    @Autowired
//    @Resource(name = "safeRoleMapper")
//    private SafeRoleMapper safeRoleMapper;
//
//    @Resource(name = "safeRoleMapper")
//    public void setMapper(SafeRoleMapper safeRoleMapper) {
//        this.mapper = safeRoleMapper;
//    }
//
//    public SafeRoleMapper getSafeRoleMapper(){
//        return safeRoleMapper;
//    }
	@Autowired
	SafeRoleMapper safeRoleMapper;
	@Autowired
	RolePrivilegeMapper rolePrivilegeMapper;
	@Autowired
	@Qualifier("privilegeManagerService")
	PrivilegeManagerService privilegeManager;

	public RoleManagerServiceImpl() {

	}

	public RoleManagerServiceImpl(String appName) {
		this.appName = appName;
	}

	public Long getPageListBySearchCount(Map<String, Object> params){
		Long count =  safeRoleMapper.getPageListBySearchCount(params);
		return count;
	}

	public Collection getPrivileges(String roleId) {
		Map param = new HashMap();
		param.put("roleId", roleId);
		Collection rolePrivileges = rolePrivilegeMapper.selectAll(param);

		// get Privilege collections
		List privileges = new ArrayList();
		Iterator itr = rolePrivileges.iterator();
		while (itr.hasNext()) {
			String privilegeId = ((RolePrivilege) itr.next()).getPrivilegeId();
			privileges.add(privilegeManager.getPrivilege(privilegeId));
		}

		return privileges;
	}

	public boolean hasPrivilege(String roleId, String pvlgId) {
		boolean hasPrivilege = false;
		Iterator itr = getPrivileges(roleId).iterator();
		while (itr.hasNext()) {
			SafePrivilege privilege = (SafePrivilege) itr.next();
			if (privilege.getId() == pvlgId) {
				hasPrivilege = true;
				break;
			}

		}

		return hasPrivilege;
	}

	public void addReservedRole(Locale locale) {
		if (logger.isInfoEnabled()) {
			logger.info("Add reserved role(s)");
		}
		addAdminRole(locale);
		Collection privilegeIds = new ArrayList();
		privilegeIds.add(new Integer(SafePrivilege.POLICY_ADMIN_ID));
		privilegeIds.add(new Integer(SafePrivilege.ASSIGN_ROLE_TO_USER_ID));
		privilegeIds.add(new Integer(SafePrivilege.ROLE_ADMIN_ID));

		if (logger.isInfoEnabled()) {
			logger.info("Assign privileges to reserved role(s)");
		}
		assignPrivileges(ADMINISTRATOR_ID, privilegeIds);
	}

	private void addAdminRole(Locale locale) {
		try {
			SafeRole role = new SafeRole();
			role.setId(String.valueOf(ADMINISTRATOR_ID));
			role.setName(I18N.getInstance().getAuthMessage(locale, Constants.SAFE_ADMINISTRATOR));
			safeRoleMapper.insert(role);

			// create it's related usercategory
			UserCategoryManagerService userCategoryManager = Factory.getUserCategoryManager(appName);
			userCategoryManager.addUserCategory(role);
		} catch (Exception e) {
			throw new DBLevelException(e);
		}
	}

	public SafeRole addRole(SafeRole role) {
		role.setId(newRoleId());
		safeRoleMapper.insert(role);

		if (logger.isInfoEnabled()) {
			logger.info("Role created: " + role);
		}

		// create related usercategory
		UserCategoryManagerService userCategoryManager = Factory.getUserCategoryManager(appName);
		try {
			userCategoryManager.addUserCategory(role);
		} catch (Exception e) {
			logger.error("", e);
			throw new DBLevelException(e);
		}
		return role;
	}

	private String newRoleId() {
		try {
			return String.valueOf(DBUtil.getSequenceNextVal("role_id"));
		} catch (SQLException e) {
			throw new DBLevelException(e);
		}
	}

	public void assignPrivileges(String roleId, Collection pvlgIds) {
		// delete original role-privilege records
		Map parm = new HashMap();
		parm.put("roleId", roleId);
		rolePrivilegeMapper.deleteBy(parm);

		// new records
//		List rolePrivileges = new ArrayList();
		Iterator itr = pvlgIds.iterator();
		while (itr.hasNext()) {
			String privilegeId = (String) itr.next();
//			rolePrivileges.add(new RolePrivilege(roleId, privilegeId));
			rolePrivilegeMapper.insert(new RolePrivilege(roleId, privilegeId));
		}
//		rolePrivilegeMapper.batchSave(rolePrivileges);

		if (logger.isInfoEnabled()) {
			logger.info("Privileges " + pvlgIds + " assigned to roleId=" + roleId);
		}
	}

	public void deleteRole(String id) {
		if (logger.isDebugEnabled()) {
			logger.debug("delete role-privilege relationships (by assigning none privilege to the role). RoleId=" + id);
		}
		// delete role-privilege relationship
		assignPrivileges(id, new ArrayList());

		if (logger.isDebugEnabled()) {
			logger.debug("delete user-role relationships. RoleId=" + id);
		}
		// delete user-role of current application usertype(s)
//		Application app = Factory.getApplicationManager().getApplication(appName);
//		Collection userTypes = app.getUserTypes();
//		Iterator itr = userTypes.iterator();
//		while (itr.hasNext()) {
//			UserType userType = (UserType) itr.next();
//			UserRoleManagerService userRoleManager = Factory.getUserRoleManager(appName, userType.getName());
//			userRoleManager.deleteUserRoles(id);
//		}
		UserRoleManagerService userRoleManager = Factory.getUserRoleManager("");
		userRoleManager.deleteUserRoles(id);
		// delete role
		safeRoleMapper.deleteByPrimaryKey(id);

		if (logger.isInfoEnabled()) {
			logger.info("Role deleted: " + id);
		}
	}

	public void deleteRolePrivilegeByPrivilege(String privilegeId) {
		rolePrivilegeMapper.deleteByPrimaryKey(privilegeId);
	}

	public Collection getAllRoles() {
		return safeRoleMapper.selectAll(null);
	}

	public Collection getLikelyRoles(String name) {
//		FieldWhereElement emt = new FieldWhereElement();
//		emt.setColumn(roleTable.getColumns()[1]);
//		emt.setCompartor(SingleValueComparator.LIKE);
//		emt.setContextValue(true);
//
//		SelectCondition cdtn = new SelectCondition();
//		cdtn.setWhereElement(emt);
//
//		Role role = new Role();
//		role.setName("%" + name + "%");
//
//		return roleSelector.select(cdtn, role);
		Map param = new HashMap();
		param.put("name", name);
		return safeRoleMapper.selectAll(param);
	}

	public SafeRole getRole(String id) {
		return safeRoleMapper.selectByPrimaryKey(id);
	}

	public void updateRole(SafeRole role) throws EntityExistException {
		safeRoleMapper.updateByPrimaryKey(role);
		if (logger.isInfoEnabled()) {
			logger.info("Role updated: " + role);
		}
	}

	public SafeRole selectById(String id) {
		return safeRoleMapper.selectByPrimaryKey(id);
	}
	
}
